/*===
- redefine S["0"] as "f"
allowed
- redefine S[0] as "f"
allowed
- redefine S["0"] as "g"
TypeError
- redefine S[0] as "g"
TypeError
- redefine S["-0"] as "g"
allowed
- redefine S[-0] as "g"
TypeError
===*/

var S = new String('foo');

print('- redefine S["0"] as "f"');
try {
    Object.defineProperty(S, '0', { value: 'f' });
    print('allowed');
} catch (e) {
    print(e.name);
}

print('- redefine S[0] as "f"');
try {
    Object.defineProperty(S, 0, { value: 'f' });
    print('allowed');
} catch (e) {
    print(e.name);
}

print('- redefine S["0"] as "g"');
try {
    Object.defineProperty(S, '0', { value: 'g' });
    print('allowed');
} catch (e) {
    print(e.name);
}

print('- redefine S[0] as "g"');
try {
    Object.defineProperty(S, 0, { value: 'g' });
    print('allowed');
} catch (e) {
    print(e.name);
}

// '-0' is a CanonicalNumericIndexString, but is considered not a match
// for string indices in StringGetOwnProperty() which is used by
// String object [[DefineOwnProperty]].
print('- redefine S["-0"] as "g"');
try {
    Object.defineProperty(S, '-0', { value: 'g' });
    print('allowed');
} catch (e) {
    print(e.name);
}

// Here the -0 ToPropertyKey() coerces to '0' and *is* thus a valid index.
print('- redefine S[-0] as "g"');
try {
    Object.defineProperty(S, -0, { value: 'g' });
    print('allowed');
} catch (e) {
    print(e.name);
}
